package class02.randoom;

/**
 * @Auther: xw
 * @Create: 2022/3/2 20:57
 * @Description:
 */
public class RandomTest {
    public static void main(String[] args) {
        //返回一个double类型的小数，范围【0,1）
//        double random = Math.random();
        int testTimes = 1000000;
        int count = 0;
        for (int i = 0; i < testTimes; i++) {
            if(Math.random() < 0.6){
                count++;
            }
        }
        System.out.println((double)count/(double)testTimes);

        System.out.println("====================");
        int k = 10;
//        Math.random() * k  [0,k-1]
        int[] counts = new int[k];
        for (int i = 0; i < testTimes; i++) {
            int v = (int)(Math.random() * k );
            counts[v]++;
        }
        for (int i = 0; i < k; i++) {
            System.out.println(i+"这个数出现了"+counts[i]+"次");
        }
        System.out.println("=====================");

        count =0;
        for (int i = 0; i < testTimes; i++) {
            if(xToXPower() < 0.6){
                count++;
            }
        }
        System.out.println((double)count/(double)testTimes);

        System.out.println("====================");
         k = 8;
//        Math.random() * k  [0,k-1]
        int[] aa = new int[k];
        for (int i = 0; i < testTimes; i++) {
            int v = f3();
            aa[v]++;
        }
        for (int i = 0; i < k; i++) {
            System.out.println(i+"这个数出现了"+aa[i]+"次");
        }
        System.out.println("=====================");

    }

    /**
     * 返回 [0,1)之间任意数的概率为x^2
     * @return
     */
    public static double xToXPower(){
        return Math.max(Math.random(),Math.random());
    }

    /**
     * 已知函数f1(),等概率返回[0,6]之间的数，那如何用f1得到等概率返回[0,7]的函数
     *      思路：得到f1()等概率返回0和1的函数，判断所需区间需要几个二进制位，然后进行位移
     *      15-61之间的函数，61-15+1 = 47个数，所以需要得到0-47之间的等概率发生器之后+15即可
     *      1+2+4+8+16+32=63，需要6个二进制位，大于47的就重做
     *
     * @return
     */
    public static int f1(){
        return (int)(Math.random()*5) +1 ;
    }

    /**
     * 随机机制， 等概率返回0和1
     * @return
     */
    public static int f2(){
        int ans = 0;
        do{
            ans = f1();
        }while(ans == 3);
        return ans < 3 ? 0 : 1;
    }

    /**
     * 等概率返回0和1 之后利用左移运算符进行二进制运算 0为000,7为111
     * @return
     */
    public static int f3(){
        return ((f2()<<2) + (f2()<<1) + (f2()));
    }

    /**
     *   返回[0,6]
     * @return
     */
    public  static int f4(){
        int ans = 0;
        do{
            ans = f3();
        }while(ans ==7);
        return ans;
    }

    /**
     *  题目：已知某黑盒函数x，不等概率返回0 和1 ，怎么得到等概率返回0和1的函数y
     *      思路 返回 0 的概率为P，那么返回1的概率为1-p
     *      要使其等概率返回 需要摇两次
     *         0    0 的时候重做
     *         1     1 的时候重做
     *         0     1 的时候返回0
     *         1     0 的时候返回1
     *         这时候0 1 等概率为p*(1-p)
     * @return
     */
    public static int x(){
        return Math.random() < 0.79 ? 0:1;
    }

    public static  int y(){
        int ans = 0;
        do{
            ans = x();
        }while(ans == x());
        return  ans;
    }
}
